﻿#define DB_MYSQL
//#define DB_ACCESS
//#define DEBUG_MESSAGES

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net.Mail;

using DAO;
using DAO.DB;

using Code;
using Code.Data;

// Tamanho maximo da questão 483 - b - 1390
// Tamanho das opçoes 270
public partial class _Default : System.Web.UI.Page
{
    #region Fields

    /// <summary>
    /// The test value.
    /// </summary>
    double testValue = -1;

    /// <summary>
    /// The test avarage pontuation.
    /// </summary>
    double approvalPercentage = -1;

    #endregion

    #region Initialization

    /// <summary>
    /// On page load.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The args</param>
    protected void Page_Load(object sender, EventArgs e)
    {    
        if (this.IsPostBack == false)
        {
            string user = this.Request.QueryString["User"];
            string test = this.Request.QueryString["Test"];

            /*string debug = this.Request.QueryString["debug"];
            if (debug != "s")
            {
                this.SetError("Sistema em manutenção.\nTente novamente daqui 1 hora.");
            }
            else
            {
                this.LoadQuestions();
            }*/

            this.LoadQuestions();
        }
    }

    /// <summary>
    /// On page load.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The args</param>
    protected void mainForm_load(object sender, EventArgs e)
    {
        //this.Response.Write("<script type=\"text/javascript\"> alert('lalalal'); </script>");
    }

    /// <summary>
    /// To load the questions.
    /// </summary>
    public void LoadQuestions()
    {
        if (this.IsPostBack == false)
        {
            string id_usuario = this.Request.QueryString["p"]; // Id_Usuario: p
            string id_test = this.Request.QueryString["w"]; // TestID: w
            string cpf = this.Request.QueryString["d"]; // cpf: d
            string modeS = this.Request.QueryString["o"]; // Mode: o
            int? mode = null;

            if (string.IsNullOrEmpty(cpf) == true)
            {
                cpf = "00000000000";
            }

            this.customData.Value = cpf;

            if (string.IsNullOrEmpty(id_test) == true)
            {
                this.SetError("Parametros invalidos.");
                return;
            }

            if (string.IsNullOrEmpty(id_usuario) == true)
            {
                if (string.IsNullOrEmpty(modeS) == true)
                {
                    this.SetError("Parametros invalidos.");
                    return;
                }
                else
                {
                    mode = int.Parse(modeS);
                }
            }
            else
            {
#if DEBUG_MESSAGES
                this.Response.Write("#User: " + id_usuario + " - id: " + id_test + "#");
#endif
            }

            // Setup the MySQL database
            DAO.DAO.Instance.Setup(DatabaseTypes.MySql, DataHelper.Instance.MySqlConnectionString);

            List<String> columns = new List<string>();
            
            // Getting Test Def data
            columns.Clear();
            columns.Add("maxTime");
            columns.Add("Id_Curso");
            columns.Add("Sortear_Questoes");

            List<Dictionary<string, object>> data = new List<Dictionary<string, object>>();
            try
            {
                DAO.DAO.Instance.Connector.Open();
                data = DAO.DAO.Instance.Connector.QueryWithColumns("select maxTime, Id_Curso, Sortear_Questoes from tb_TestDef WHERE id_testDef=" + id_test, columns);
                DAO.DAO.Instance.Connector.Close();
            }
            catch
            {
                this.SetError("A prova não possui nenhuma questão.");
                return;
            }

            //DateTime? testStartDate = null;
            //DateTime? testEndDate = null;
            int? testMaxTimeMinutes = null;
            int? Id_Curso = null;
            int? Sortear_Questoes = null;

            try
            {
                object maxTimeValue = null;
                data[0].TryGetValue("maxTime", out maxTimeValue);

                object Id_CursoValue = null;
                data[0].TryGetValue("Id_Curso", out Id_CursoValue);
                Id_Curso = (int)Id_CursoValue;

                object Sortear_QuestoesValue = null;
                data[0].TryGetValue("Sortear_Questoes", out Sortear_QuestoesValue);
                Sortear_Questoes = (int)Sortear_QuestoesValue;

                DateTime testDuration = DateTime.Parse(maxTimeValue as string);
                testMaxTimeMinutes = testDuration.Hour * 60 + testDuration.Minute;
            }
            catch (Exception error1)
            {
                //this.Response.Write("Erro para a prova: " + id_test + " error: " + error1.Message);
                this.SetError("#Erro: " + error1.Message + "\n" + error1.StackTrace + "\n" + error1.TargetSite);
                return;
            }

            string sqlQuery = "";

            // See if the user is valid for the test, Matriculas
            columns.Clear();
            columns.Add("Nome");
            sqlQuery = "SELECT tb_Usuarios.Nome FROM (tb_Usuarios INNER JOIN tb_Curriculums ON tb_Usuarios.Id_Usuario = tb_Curriculums.Id_Usuario) INNER JOIN tb_TestDef ON tb_Curriculums.Id_Curso = tb_TestDef.Id_Curso WHERE tb_Curriculums.Id_Usuario = " + id_usuario + " AND  tb_Curriculums.Id_Curso = " + Id_Curso;
            DAO.DAO.Instance.Connector.Open();
            data = DAO.DAO.Instance.Connector.QueryWithColumns(sqlQuery, columns);
            DAO.DAO.Instance.Connector.Close();

            if (data.Count > 0)
            {
            }
            else
            {
                this.SetError("O usuário não esta registrado no curso referente a esta prova.");
                return;
            }

            // ** OK the user is valid for the test //

            // Getting Test Status data
            columns.Clear();
            columns.Add("Id_Usuario");
            columns.Add("done");
            columns.Add("startDate");
            columns.Add("Questoes_Sorteadas");
            
            // See if the user has already started the test
            DAO.DAO.Instance.Connector.Open();
            string sqlUsuario = "select Id_Usuario, done, startDate, Questoes_Sorteadas from tb_TestStatus WHERE Excluido <> 1 AND id_test=" + id_test + " and Id_Usuario=" + id_usuario + " AND cpf='" + cpf + "'";
            data = DAO.DAO.Instance.Connector.QueryWithColumns(sqlUsuario, columns);
            DAO.DAO.Instance.Connector.Close();

            try
            {
                //object id_testValue = null;
                object Id_UsuarioValue = null;
                object doneValue = null;
                object studentStartDateText = null;
                object Questoes_SorteadasValue = null;
                if (data.Count > 0)
                {                   
                    // ** OK the user already have a Test Status //
                    data[0].TryGetValue("Id_Usuario", out Id_UsuarioValue);
                    data[0].TryGetValue("done", out doneValue);                    
                    data[0].TryGetValue("startDate", out studentStartDateText);
                    data[0].TryGetValue("Questoes_Sorteadas", out Questoes_SorteadasValue);
                    //this.Response.Write("O usuario esta cadastrado no TestStatus.");
                }
                else
                {
                    // ** The user does not have a Test Staus //
                    //this.Response.Write("O usuario nao esta cadastrado no TestStatus.");
                    Id_UsuarioValue = id_usuario;
                    doneValue = 0;
                    DAO.DAO.Instance.Connector.Open();
                    
                    // The questions must be randomized here
                    if (Sortear_Questoes != null && Sortear_Questoes > 0)
                    {
                        //this.ShowAlert("Randomizar: " + Sortear_Questoes);
                        this.RandomizeQuestions(DAO.DAO.Instance.Connector, Sortear_Questoes.Value, int.Parse(id_usuario), int.Parse(id_test));
                    }
                    else
                    {
                        //this.ShowAlert("NAO Randomizar: " + Sortear_Questoes);
                        DAO.DAO.Instance.Connector.Execute("INSERT INTO tb_TestStatus (Id_Usuario, id_test) VALUES (" + id_usuario + "," + id_test + ")");
                    }

                    DAO.DAO.Instance.Connector.Close();
                }

                //this.Response.Write("IdTest: " + id_test + " Id_Usuario: " + Id_UsuarioValue + " Done:" + doneValue);
                if ((int)doneValue == 0)
                {
                    DateTime now = DateTime.Now;
                    // To see if the test is available
                    //if (now >= testStartDate && now <= testEndDate)
                    {
                        float secsToFinish = testMaxTimeMinutes.Value * 60;
                        // To see if still have time to make the test.
                        if (string.IsNullOrEmpty(studentStartDateText as string) == false)
                        {
                            DateTime studentStartDate = DateTime.Parse(studentStartDateText as string);
                            TimeSpan timeDiffer = DateTime.Now.Subtract(studentStartDate);
                            if (timeDiffer.TotalMinutes >= testMaxTimeMinutes.Value)
                            {
                                secsToFinish = 0;
                            }
                            else
                            {
                                secsToFinish = (float)(testMaxTimeMinutes.Value - timeDiffer.TotalMinutes) * 60;
                            }
                        }
                        
                        string questionBufferData = DataHelper.Instance.GetQuestionsWithoutSolution(DAO.DAO.Instance.Connector, int.Parse(id_test), Sortear_Questoes.Value, out this.testValue, out this.approvalPercentage, true, int.Parse(id_usuario));
                        //Response.Write(questionBufferData);
                        
                        if (questionBufferData == "error")
                        {
                            this.SetError("A prova não possui nenhuma questão vinculada.");
                            return;
                        }

                        this.transferArea.Value = questionBufferData;
                        this.additionalData.Value = id_test + "#" + id_usuario + "#" + secsToFinish;
                        this.SetOkMessage();
                    }
                    /*
                    else
                    {
                        this.SetError("A prova não está disponível.");
                    }
                    */
                }
                else
                {
                    this.SetError("O usuário já concluiu a prova");
                }
            }
            catch (Exception error2)
            {

                this.SetError("O usuario nao esta cadastrado para a prova: " + id_test + "\n\nDetalhes do erro: " + error2.Message +"\n" + error2.StackTrace + "\n" + error2.TargetSite);
                return;
            }
        }
    }

    /// <summary>
    /// Shows an alert.
    /// </summary>
    /// <param name="msg"></param>
    private void ShowAlert(string msg)
    {
        this.Response.Write("<script>alert('" + msg + "');</script>");
    }

    /// <summary>
    /// To randomize the questions
    /// </summary>
    /// <param name="connector"></param>
    /// <param name="questions"></param>
    /// <param name="id_usuario"></param>
    /// <param name="id_test"></param>
    protected void RandomizeQuestions(BaseConnector connector, int questions, int id_usuario, int id_test)
    {
        string randomizedQuestions = "";
        var reader = connector.QueryWithReader("SELECT id_question FROM tb_TestsQuestions WHERE tb_TestsQuestions.id_testDef=" + id_test);

        // Getting all questions ids
        List<int> testIds = new List<int>();
        while (reader.Read())
        {
            testIds.Add((int)reader["id_question"]);
        }

        if (testIds.Count == 0)
        {
            throw new Exception("A prova não possui questões vinculadas !");
        }

        // Randomizing some questions
        for (int i = 0; i < questions; ++i)
        {
            Random rand = new Random(DateTime.Now.Millisecond);           
            int number = rand.Next(0, testIds.Count);            
            randomizedQuestions += "" + testIds[number] + ",";
            //this.Response.Write("N: " + number + " id: " + testIds[number] + " C: " + testIds.Count + "<br />");
            testIds.RemoveAt(number);
        }
        reader.Close();

        // Saving the randomized questions ids on the Test Status
        connector.Execute("INSERT INTO tb_TestStatus (Id_Usuario, id_test, Questoes_Sorteadas) VALUES (" + id_usuario + "," + id_test + ", '" + randomizedQuestions  + "')");
    }

    /// <summary>
    /// To set an error message into the question div.
    /// </summary>
    /// <param name="message"></param>
    protected void SetError(string message)
    {
        Label error = this.FindControl("errorField") as Label;
        error.Text = message;
    }

    /// <summary>
    /// To set tge initial message.
    /// </summary>
    protected void SetOkMessage()
    {
        string message = "";
        message += "Clique em iniciar e responda às perguntas.";
        message += "<br/>";
        message += "A avaliação tem valor de " + this.testValue + " pontos e a média para concluir o curso com sucesso é " + this.approvalPercentage + "% !";
        message += "<br/>";
        message += "Desejamos que seu curso seja concluído com sucesso!";

        this.SetError(message);
    }

    #endregion
}